#ifndef _BASE_
#define _BASE_

#ifndef NULL
#define NULL 0
#endif

typedef __int8	schar;
typedef __int16 sshort;
typedef __int32 sint;
typedef __int64 sint64;
typedef unsigned __int8 uchar;
typedef unsigned __int16 ushort;
typedef unsigned __int32 uint;
typedef unsigned __int64 uint64;

// just an include hack here. winsock.h(which is used by raknet.. maybe) must be included before windows
#include "raknet\WindowsIncludes.h"

//#include "CSLock.h"

inline float dist2(float x1, float y1, float x2, float y2) {
	return ((x1-x2)*(x1-x2)+(y1-y2)*(y1-y2));
}

namespace air {

//thread-safe circular list avoiding deadlock
	/*struct MessageNode {
	public:
		uchar msgId;
		//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		char value[300]; //TODO might overweight!!!!!
		//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
		uint size;
		MessageNode *next;
		MessageNode(): msgId(0), size(0), next(NULL) { 
			memset(value, 0, sizeof(value));
		}
	};

	class MessageQueue {
	public:
		MessageQueue(int _capacity = 50) :capacity(_capacity) {
			Q = new MessageNode[capacity + 1];
			for (uint i = 0; i < capacity; i++) {
				(Q+i)->next = Q+(i+1);
			}
			Q[capacity].next = Q;
			head = tail = Q;
		}

		~MessageQueue() {
			delete[] Q;
		}

		bool enqueue(uchar _msgId, char* src, uint size) {
			if (tail->next != head) {
				tail->next->msgId = _msgId;
				tail->next->size = size;
				if (src && size) {
					memcpy(tail->next->value, src, size);
				}
				tail = tail->next;
				return true;
			} else {
				q_h_cs.Enter();
				head = head->next;
				tail->next->msgId = _msgId;
				tail->next->size = size;
				if (src && size) {
					memcpy(tail->next->value, src, size);
				}
				tail = tail->next;
				q_h_cs.Leave();
				return false;
			}
		}

		uchar dequeue(char* dest, unsigned short *length) {
			q_h_cs.Enter();
			if (head != tail) {
				*length = head->next->size;
				if (*length) {
					memcpy(dest, head->next->value, head->next->size);
				}
				uchar msgId = head->next->msgId;
				head = head->next;
				q_h_cs.Leave();
				return msgId;
			} else {
				q_h_cs.Leave();
				return (uchar)0;
			}
		}

	private:
		CriticalSection q_h_cs;
		volatile MessageNode *head, *tail;
		MessageNode *Q;
		uint capacity;
	};*/


	template <class T>
	struct Node {
		T val;
		Node *next, *prev;
		Node(): next(NULL), prev(NULL) {
		}
		Node (const T& E): next(NULL) {
			this->val = E;
		}
	};


// list
	template <class T>
	class Alist {
	public:
		Alist(): _size(0) {
			m_head = new Node<T>;
			m_tail = new Node<T>;
			m_head->next = m_tail;
			m_tail->prev = m_head;
		}

		~Alist() {
			clear();
			delete m_head;
			delete m_tail;
		}

		Node<T>* append(const T& E) {
			Node<T>* p = new Node<T>(E);
			p->prev = m_tail->prev;
			p->next = m_tail;

			p->prev->next = p;
			m_tail->prev = p;

			++_size;
			return p;
		}

		Node<T>* remove(Node<T>* v) {
			if (v == m_head || v == m_tail) {
				return NULL;
			}
			Node<T>* p = v->next;
			v->prev->next = p;
			v->next->prev = v->prev;
			delete v;
			--_size;
			return p;
		}

		Node<T>* Head() {
			return m_head;
		}

		Node<T>* Tail() {
			return m_tail;
		}

		void clear() {
			Node<T>* p = m_head->next;
			while (p != m_tail) {
				Node<T>* q = p->next;
				delete p;
				p = q;
			}

			m_head->next = m_tail;
			m_tail->prev = m_head;
			_size = 0;
		}

		int size() const {
			return _size;
		}

	private:
		int _size;
		Node<T> *m_head, *m_tail;
	};
}


#endif 
